<?php
/*
 You may not change or alter any portion of this comment or credits
 of supporting developers from this source code or any supporting source code
 which is considered copyrighted (c) material of the original comment or credit authors.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

/**
* Sqlutility For Xoops
*
* @copyright The XOOPS project http://sourceforge.net/projects/xoops/
* @license http://www.fsf.org/copyleft/gpl.html GNU public license
* @package kernel
* @subpackage database
* @since 1.0.0
* @author Kazumi Ono <onokazu@xoops.org>
* @version $Id: sqlutility.php 3563 2009-09-05 11:01:35Z trabis $
*/
defined('XOOPS_ROOT_PATH') or die('Restricted access');

/**
* provide some utility methods for databases
*
* @author Kazumi Ono <onokazu@xoops.org>
* @copyright copyright (c) 2000-2003 XOOPS.org
* @package kernel
* @subpackage database
*/
class SqlUtility {
    /**
    * Function from phpMyAdmin (http://phpwizard.net/projects/phpMyAdmin/)
    *
    * Removes comment and splits large sql files into individual queries
    *
    * Last revision: September 23, 2001 - gandon
    *
    * @param array $ the splitted sql commands
    * @param string $ the sql commands
    * @return boolean always true
    * @access public
    */
    function splitMySqlFile(&$ret, $sql)
    {
        $sql = trim($sql);
        $sql_len = strlen($sql);
        $char = '';
        $string_start = '';
        $in_string = false;

        for ($i = 0; $i < $sql_len; ++$i) {
            $char = $sql[$i];
            // We are in a string, check for not escaped end of
            // strings except for backquotes that can't be escaped
            if ($in_string) {
                for (;;) {
                    $i = strpos($sql, $string_start, $i);
                    // No end of string found -> add the current
                    // substring to the returned array
                    if (!$i) {
                        $ret[] = $sql;
                        return true;
                    }
                    // Backquotes or no backslashes before
                    // quotes: it's indeed the end of the
                    // string -> exit the loop
                    else if ($string_start == '`' || $sql[$i-1] != '\\') {
                        $string_start = '';
                        $in_string = false;
                        break;
                    }
                    // one or more Backslashes before the presumed
                    // end of string...
                    else {
                        // first checks for escaped backslashes
                        $j = 2;
                        $escaped_backslash = false;
                        while ($i - $j > 0 && $sql[$i - $j] == '\\') {
                            $escaped_backslash = !$escaped_backslash;
                            $j++;
                        }
                        // ... if escaped backslashes: it's really the
                        // end of the string -> exit the loop
                        if ($escaped_backslash) {
                            $string_start = '';
                            $in_string = false;
                            break;
                        }
                        // ... else loop
                        else {
                            $i++;
                        }
                    } // end if...elseif...else
                } // end for
            } // end if (in string)
            // We are not in a string, first check for delimiter...
            else if ($char == ';') {
                // if delimiter found, add the parsed part to the returned array
                $ret[] = substr($sql, 0, $i);
                $sql = ltrim(substr($sql, min($i + 1, $sql_len)));
                $sql_len = strlen($sql);
                if ($sql_len) {
                    $i = -1;
                } else {
                    // The submited statement(s) end(s) here
                    return true;
                }
            } // end else if (is delimiter)
            // ... then check for start of a string,...
            else if (($char == '"') || ($char == '\'') || ($char == '`')) {
                $in_string = true;
                $string_start = $char;
            } // end else if (is start of string)
            // for start of a comment (and remove this comment if found)...
            else if ($char == '#' || ($char == ' ' && $i > 1 && $sql[$i-2] . $sql[$i-1] == '--')) {
                // starting position of the comment depends on the comment type
                $start_of_comment = (($sql[$i] == '#') ? $i : $i-2);
                // if no "\n" exits in the remaining string, checks for "\r"
                // (Mac eol style)
                $end_of_comment = (strpos(' ' . $sql, "\012", $i + 2))
                ? strpos(' ' . $sql, "\012", $i + 2)
                : strpos(' ' . $sql, "\015", $i + 2);
                if (!$end_of_comment) {
                    // no eol found after '#', add the parsed part to the returned
                    // array and exit
                    // RMV fix for comments at end of file
                    $last = trim(substr($sql, 0, $i-1));
                    if (!empty($last)) {
                        $ret[] = $last;
                    }
                    return true;
                } else {
                    $sql = substr($sql, 0, $start_of_comment) . ltrim(substr($sql, $end_of_comment));
                    $sql_len = strlen($sql);
                    $i--;
                } // end if...else
            } // end else if (is comment)
        } // end for
        // add any rest to the returned array
        if (!empty($sql) && trim($sql) != '') {
            $ret[] = $sql;
        }
        return true; // end for
    }

    /**
    * add a prefix.'_' to all tablenames in a query
    *
    * @param string $query valid SQL query string
    * @param string $prefix prefix to add to all table names
    * @return mixed FALSE on failure
    */
    function prefixQuery($query, $prefix)
    {
        $pattern = "/^(INSERT[\s]+INTO|CREATE[\s]+TABLE|ALTER[\s]+TABLE|UPDATE)(\s)+([`]?)([^`\s]+)\\3(\s)+/siU";
        $pattern2 = "/^(DROP TABLE)(\s)+([`]?)([^`\s]+)\\3(\s)?$/siU";
        if (preg_match($pattern, $query, $matches) || preg_match($pattern2, $query, $matches)) {
            $replace = "\\1 " . $prefix . "_\\4\\5";
            $matches[0] = preg_replace($pattern, $replace, $query);
            return $matches;
        }
        return false;
    }
}

?>